package dkbta.ontology.loading;

import static dkbta.ontology.elements.ElementType.STAT;
import static dkbta.ontology.elements.ElementType.SUBJECTSTAT;
import static dkbta.ontology.loading.OntologyParser.getXmlElement;
import static dkbta.ontology.loading.OntologyParser.parsePercentRange;
import static dkbta.ontology.loading.OntologyParser.parseValueConsdition;

import java.util.EnumSet;
import java.util.Set;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import dkbta.ontology.Ontology;
import dkbta.ontology.elements.ElementType;
import dkbta.ontology.elements.stat.StatDef;
import dkbta.ontology.loading.OntologyParser.ElementParser;
import dkbta.ontology.values.PercentValues;
import dkbta.ontology.values.ValueCondition;

final class StatParser implements ElementParser{
	private final Set<ElementType> _invalidAbstractionElements = EnumSet.of(STAT, SUBJECTSTAT);
	
	private final Ontology _ontology;

	public StatParser(Ontology ontology){
		_ontology = ontology;
	}

	@Override
	public ElementType getElementType(){
		return ElementType.STAT;
	}

	public void parseElement(Element stat, String name, String componentType)
			throws OntologyException{

		Element afsElement = getXmlElement(stat, "AbstractedFrom");
		if (afsElement == null){
			throw new OntologyException("No abstracted-from element");
		}

		Element afElement = getAfElement(afsElement);

		ValueCondition valueCondition = parseValueConsdition(afElement, afElement
				.getTagName(), _invalidAbstractionElements, false);
		if (valueCondition == null){
			throw new OntologyException("A statistical abstraction must have "
					+ "a value condition on an element from the ontology");
		}

		PercentValues percentRange = parsePercentRange(stat, true, null);
		if (percentRange == null){
			throw new OntologyException("A statistical abstraction must have "
					+ "valid percent values");
		}

		boolean ignorePatientsWithoutElement = false;
		Element ignorePatientsWithoutElementNode = getXmlElement(stat,
			"IgnorePatientsWithoutElement");
		if (ignorePatientsWithoutElementNode != null){
			ignorePatientsWithoutElement = Boolean
					.parseBoolean(ignorePatientsWithoutElementNode.getAttribute("value"));
		}

		StatDef sd = new StatDef(name, componentType, valueCondition, percentRange,
				ignorePatientsWithoutElement);
		_ontology.addStat(sd);
	}

	private Element getAfElement(Element afsElement) throws OntologyException{
		NodeList childNodes = afsElement.getChildNodes();

		int elementNodeCount = 0;
		Element afElement = null;
		for (int i = 0; i < childNodes.getLength(); ++i){
			Node node = childNodes.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE){
				elementNodeCount++;
				afElement = (Element)node;
			}
		}

		if (elementNodeCount != 1){
			throw new OntologyException(
					"A statistical abstraction can be abstracted from only one element and not "
							+ elementNodeCount);
		}
		return afElement;
	}
}